package utils

import (
	"sync"
)

type SyncMap[K comparable, V any] struct {
	m  Map[K, V]
	mu sync.Mutex
}

func NewSyncMap[K comparable, V any](m Map[K, V]) Map[K, V] {
	return &SyncMap[K, V]{
		m: m,
	}
}

// Put inserts element into the map.
func (m *SyncMap[K, V]) Put(key K, value V) {
	m.mu.Lock()
	m.m.Put(key, value)
	m.mu.Unlock()
}

// Get searches the element in the map by key and returns its value or nil if key is not found in map.
// Second return parameter is true if key was found, otherwise false.
func (m *SyncMap[K, V]) Get(key K) (value V, found bool) {
	value, found = m.m.Get(key)
	return
}

// Remove removes the element from the map by key.
func (m *SyncMap[K, V]) Remove(key K) {

	m.mu.Lock()
	m.m.Remove(key)
	m.mu.Unlock()
}

// Empty returns true if map does not contain any elements
func (m *SyncMap[K, V]) Empty() bool {
	return m.Size() == 0
}

// Size returns number of elements in the map.
func (m *SyncMap[K, V]) Size() int {
	return m.m.Size()
}

// Keys returns all keys (random order).
func (m *SyncMap[K, V]) Keys() []K {

	return m.m.Keys()
}

// Values returns all values (random order).
func (m *SyncMap[K, V]) Values() []V {

	return m.m.Values()
}

// Values returns all values (random order).
func (m *SyncMap[K, V]) EntrySet() []Entry[K, V] {

	return m.m.EntrySet()
}

// Clear removes all elements from the map.
func (m *SyncMap[K, V]) Clear() {
	m.mu.Lock()
	m.m.Clear()
	m.mu.Unlock()
}

// 返回原生map
func (m *SyncMap[K, V]) Map() map[K]V {
	return m.m.Map()
}

// String returns a string representation of container
func (m *SyncMap[K, V]) String() string {
	str := "SyncMap\n"
	str += m.m.String()
	return str
}

// ToJSON outputs the JSON representation of the SyncMap.
func (m *SyncMap[K, V]) ToJSON() ([]byte, error) {
	return m.m.ToJSON()
}

// FromJSON populates the SyncMap from the input JSON representation.
func (m *SyncMap[K, V]) FromJSON(data []byte) error {

	return m.m.FromJSON(data)
}

// UnmarshalJSON @implements json.Unmarshaler
func (m *SyncMap[K, V]) UnmarshalJSON(bytes []byte) error {
	return m.m.UnmarshalJSON(bytes)
}

// MarshalJSON @implements json.Marshaler
func (m *SyncMap[K, V]) MarshalJSON() ([]byte, error) {
	return m.m.ToJSON()
}
